//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/.
// 			VisualNovelToolkit		     /_/_/_/_/_/_/_/_/_/.
// Copyright ©2013 - Sol-tribe.	/_/_/_/_/_/_/_/_/_/_/_/_/_/.
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace ViNoToolkit{

	public class KAGTagParser{
		static public int m_SelectionIndex = 0;
		static public string m_CurrentMessageTarget = "TextBox";

	//	public string[] tags;
	//	delegate void OnTag( Hashtable attrTable , List<byte> byteList );
	//	public event OnTag m_OnTagDelegate;
		static public void Parse( string tag , Hashtable attrTable , List<byte> byteList ){
			// TODO . THIS IS TEST CODE.
			// Do NOT include this in PRODUCT !!!.
			switch( tag ){
	//			case "image":			KAGTagParser.OnImageTag( attrTable , byteList );			break;
				case "wait" :			KAGTagParser.OnWaitTag( attrTable , byteList );				break;
				case "link"	:			KAGTagParser.OnLinkTag( attrTable , byteList );				break;
				case "jump" :			KAGTagParser.OnJumpTag( attrTable , byteList );				break;
				case "layopt" :			KAGTagParser.OnLayOptTag( attrTable , byteList );			break;
				case "loadscene":		KAGTagParser.OnLoadSceneTag( attrTable , byteList );		break;
				case "current":			KAGTagParser.OnCurrentTag( attrTable , byteList );			break;
				case "anim":			KAGTagParser.OnAnimTag( attrTable , byteList );				break;
				case "object":			KAGTagParser.OnObjectTag( attrTable , byteList );			break;
				case "instantiate":		
					string resourcePath = "";//attrTable[ "storage"] as string;
					if( attrTable.ContainsKey( "storage") ){
						resourcePath = attrTable[ "storage"] as string;
					}
					else{
						Debug.LogError( "[instantiate] tag must have \"storage\" attribute." );
					}						
					string parentName = "";
					if( attrTable.ContainsKey( "parent") ){
						parentName = attrTable[ "parent"] as string;
					}
					ByteCodeScriptTools.AddLoadResourceCode( byteList , resourcePath );
					ByteCodeScriptTools.AddCreateGOCode( byteList , parentName );	
					break;	

				// Trigger Event Series.
	//			case "jump":
	//			case "button":
				case "loadlevel":
					string levelName = attrTable[ "name"] as string;
					ByteCodeScriptTools.AddTextLiteralCode( byteList , levelName );
					ByteCodeScriptTools.AddMessagingCode( byteList , "env" , OpcodeMessaging.LOAD_LEVEL );			
					break;
			
				case "sendevent":
				case "image":
				case "condition":
				case "setflag":		
				case "destroy":		
				case "getuserinput":
				case "definescene":
				case "defineactor":
				case "font":
				case "eval":
				case "if_":
				case "endif":
				case "setpropactor":
				case "enterscene":
				case "enteractor":
				case "addstate":
				case "moveactor":
				case "exitactor":
				case "exitscene":
				case "settext":
				case "showsystemui":
				case "hidesystemui":
				case "changestate":
				case "stopbgm":
				case "shake":
				case "playbgm":
				case "playse":
				case "playvoice":
				case "xchgbgm":
				case "fadeoutbgm":
				case "trans":			
					attrTable["eventType"] = tag;
					KAGTagParser.OnTriggerEventWithArgsTag( attrTable , byteList );
					break;	

				// All of the TAG is united to this !.
				case "triggerevent":	
					if( attrTable.Count > 1 ){
						KAGTagParser.OnTriggerEventWithArgsTag( attrTable , byteList );
						break;
					}
					else{
						string eventType = attrTable[ "eventType" ] as string;
						KAGTagParser.OnTriggerEventTag( eventType , byteList );
						break;					
					}
					
	//			case "playbgm":			KAGTagParser.OnPlayBGMTag( attrTable , byteList );		break;
			}
		}

		static public void OnTriggerEventTag( string eventType , List<byte> byteList ){
			ByteCodeScriptTools.AddTextLiteralCode( byteList , eventType );		
			ByteCodeScriptTools.AddMessagingCode( byteList , " " , OpcodeMessaging.TRIGGER_EVENT );
		}

		static public void OnTriggerEventWithArgsTag( Hashtable attrTable , List<byte> byteList ){
			ByteCodeScriptTools.AddTablePairsCode( byteList , attrTable );
			ByteCodeScriptTools.AddMessagingCode( byteList , " " , OpcodeMessaging.TRIGGER_EVENT_WITH_ARGS );
		}

		static public void OnLayOptTag( Hashtable attrTable , List<byte> byteList ){
			ByteCodeScriptTools.AddTablePairsCode( byteList , attrTable );
			byteList.Add( Opcode.LAYOPT );
		}

		static public void OnLoadSceneTag( Hashtable attrTable , List<byte> byteList ){
			if( attrTable.ContainsKey( "storage" ) ){
				string resourcePath = attrTable[ "storage" ] as string;
				ByteCodeScriptTools.AddTextLiteralCode( byteList , resourcePath );
				byteList.Add( Opcode.LOAD_RESOURCE );		

				ByteCodeScriptTools.AddTablePairsCode( byteList , attrTable );
				byteList.Add( Opcode.LOAD_SCENE );	

	#if UNITY_EDITOR
				if( ! Application.isPlaying ){
					LoadSceneNode node = ViNoToolkit.KAGInterpreter.m_CurrentNode.AddComponent<LoadSceneNode>();
					node.sceneName = resourcePath;
				}
	#endif					
			}
			else{
				Debug.LogError( "[loadscene] Parse Error ! storage attribute Not Found." );
			}
		}

		static public void OnImageTag( Hashtable attrTable , List<byte> byteList ){
			// Set up Attribute. 
			string targetLayer = "base";
			string resourcePath = "";
			if( attrTable.ContainsKey( "storage" ) ){
				resourcePath = attrTable[ "storage" ] as string;
				if( attrTable.ContainsKey( "layer" ) ){
					targetLayer = attrTable[ "layer" ] as string;
				}
				ByteCodeScriptTools.AddTextLiteralCode( byteList , resourcePath );		
				byteList.Add( Opcode.LOAD_RESOURCE );				
				ByteCodeScriptTools.AddMessagingCode( byteList , targetLayer , OpcodeMessaging.SET_RESOURCE_AS_TEXTURE );		
			}
			else{
				Debug.LogError( "[image] Parse Error ! storage attribute Not Found." );
			}
		}

		static public void OnWaitTag( Hashtable attrTable , List<byte> byteList ){
			if( attrTable.ContainsKey( "time" ) ){
				int milliSec = int.Parse( attrTable[ "time" ] as string );
				float sec = (float)milliSec/1000f;
				CodeGenerator.GenerateWaitCode( byteList , sec );
	#if UNITY_EDITOR
				if( ! Application.isPlaying ){
					WaitNode wait = ViNoToolkit.KAGInterpreter.m_CurrentNode.AddComponent<WaitNode>();
					wait.m_WaitSec = sec;
				}
	#endif					

			}
			else{
				Debug.LogError( "[wait] Parse Error ! time attribute Not Found." );
			}
		}

		static public void OnJumpTag( Hashtable attrTable , List<byte> byteList ){
	#if false
			attrTable["eventType"] = "jump";
			OnTriggerEventWithArgsTag( attrTable , byteList );
	//		byteList.Add( Opcode.STOP );

	#else		
			string target = "start";
			if( attrTable.ContainsKey( "target" ) ){
				target = attrTable[ "target" ] as string;
				target = target.Replace( "*" , "" );
			}
			if( attrTable.ContainsKey( "storage" ) ){
				// TODO. Load another Scenario.

			}		
			ByteCodeScriptTools.AddJumpTargetCode( byteList , target );	
	#endif		
		}

		static public void OnLinkTag( Hashtable attrTable ,List<byte> byteList ){
			ByteCodeScriptTools.AddTextLiteralCode( byteList , "" );		
			byteList.Add( Opcode.SELECTIONS );

			m_SelectionIndex = 0;
		}

		static public void OnCurrentTag( Hashtable attrTable , List<byte> byteList ){
			// Set up Attribute. 
			if( attrTable.ContainsKey( "layer" ) ){
				m_CurrentMessageTarget = attrTable[ "layer" ] as string;
			}
			else{
				Debug.LogError( "[current] Parse Error ! current attribute Not Found." );
			}
		}

		static public void OnAnimTag( Hashtable attrTable ,List<byte> byteList ){
			if( attrTable.ContainsKey( "name" ) ){
				ByteCodeScriptTools.AddTablePairsCode( byteList , attrTable );
				ByteCodeScriptTools.AddMessagingCode( byteList , attrTable[ "name" ] as string , OpcodeMessaging.TWEEN );	
			}
			else{
				Debug.LogError( "target name attribute not set." );
			}
		}

		static private ViNoSceneManager m_SmInst;
		static public void OnObjectTag( Hashtable attrTable ,List<byte> byteList ){
			if( attrTable.ContainsKey( "name" ) ){
				if( ! attrTable.ContainsKey( "parentname" ) ){
					if( m_SmInst == null ){
						m_SmInst = GameObject.FindObjectOfType( typeof(ViNoSceneManager) ) as ViNoSceneManager;
					}
					attrTable["parentname"] = m_SmInst.theSavedPanel.name;
				}
				ByteCodeScriptTools.AddTablePairsCode( byteList , attrTable );
				byteList.Add( Opcode.SCENE_NODE );

	#if UNITY_EDITOR
				if( ! Application.isPlaying ){
					ViNoSceneNode node = ViNoToolkit.KAGInterpreter.m_CurrentNode.AddComponent<ViNoSceneNode>();
					node.singleNodeData = SceneCreator.CreateNodeData( attrTable );
				}
	#endif					

			}
			else{
				Debug.LogError( "target name attribute not set." );
			}
		}


	}
}
